Core.Test = function() {
	this.envs = {};
	this.suites = {};
};

Core.Test.prototype = {
	
	/**
	 * Registers environment for later usage in test cases.
	 */
	registerEnvironment: function(name, env) {
		Core.assert(!this.envs[name], "Environment with name '" + name + "' already exists.");
		this.envs[name] = env;
	},
	
	/**
	 * Returns environment corresponding to the given key.
	 */
	getEnvironment: function(name) {
		Core.assert(this.envs[name], "Environment with name '" + name + "' not found.");
		return this.envs[name];
	},
	
	/**
     * Subscribes custom tear down function to the Test.Runner.
     * @param func - tear down function.
     */
    registerCustomTearDown : function(func) {
	    Test.Runner.subscribe(Test.Runner.TEST_PASS_EVENT, func);
	    Test.Runner.subscribe(Test.Runner.TEST_FAIL_EVENT, func);
    },
	
	/**
	 * Registers test case.
	 * Test group & name have to be defined.
	 */
	registerTest: function(test) {
		Core.assert(test.name, "Test name not defined.");
		Core.assert(test.group, "Test group not defined.")
		
		if(!this.suites[test.group]) { this.suites[test.group] = []; }
		this.suites[test.group].push(test);
	},
	
	/**
	 * Runs the master test suite.
	 */
	runTests: function() {
		this._createConsole();
		this._subscribeDefaultHandlers();
		this._createRootSuite();
		Env.log("Started cover with suites:\n" + this._getSelectedSuites().join(", "), "success", "TestRunner");
	    Test.Runner.run();
	},
	
	/**
	 * Creates YUI Console to handle Test.Runner output.
     */
    _createConsole : function() {
    	var console = new Console({style: "inline", height: 450, width: 1000, printTimeout: 200});
    	console.plug(Plugin.ConsoleFilters, {category: {info: false, pass: false}});
		console.render(document.body);
    },
    
	/**
	 * Subscribes default handlers to the Test.Runner.
	 */
    _subscribeDefaultHandlers : function() {
	    Test.Runner.subscribe(Test.Runner.COMPLETE_EVENT, Core.Test.Events.suiteFinish);
	    Test.Runner.subscribe(Test.Runner.TEST_PASS_EVENT, Core.Test.Events.testFinish);
	    Test.Runner.subscribe(Test.Runner.TEST_FAIL_EVENT, Core.Test.Events.testFinish);
    },
	
	/**
	 *Creates master suite & adds all of the selected test suites.
	 */
    _createRootSuite : function() {
    	var	runner = this, suites = this.suites;
		Test.Runner.masterSuite = new Test.Suite("Master Suite");
		
		Array.each(this._getSelectedSuites(), function(selected) {
			Core.assert(suites[selected], "Suite for '" + selected + "' not found.");
			
			var suite = new Test.Suite(selected);
			Array.each(suites[selected], function(fixture) {
				if(!fixture.disabled) { suite.add(new Core.Test.Environment(fixture, runner)); }
			});
			Test.Runner.add(suite);
		});
    },
    
    /**
	 * Returns selected suites from the browser query string.
	 * If no suites were declared, returns empty array.
	 */
    _getSelectedSuites : function() {
	    var suites = History.getQueryStringParameter("suites");
	    return suites ? suites.replace(/ */g, '').split(',') : Object.keys(this.suites);
    }
};

Core.Test = new Core.Test();